import {
  ActionReducerMap,
  createSelector,
  createFeatureSelector,
  ActionReducer,
  MetaReducer
} from "@ngrx/store";
import { environment } from "../../environments/environment";
import * as fromRouter from "@ngrx/router-store";

import * as fromTrade from "@/trade/store/reducers/symbol.reducer";
import * as fromUser from "@/user/store/reducers/user.reducer";
import * as fromAssets from "@/assets/store/reducers/assets.reducer";
import * as fromMain from "@/main/store/reducers/main.reducer";

/**
 * storeFreeze prevents state from being mutated. When mutation occurs, an
 * exception will be thrown. This is useful during development mode to
 * ensure that none of the reducers accidentally mutates the state.
 */
import { storeFreeze } from "ngrx-store-freeze";

/**
 * Every reducer module's default export is the reducer function itself. In
 * addition, each module should export a type or interface that describes
 * the state of the reducer plus any selector functions. The `* as`
 * notation packages up all of the exports into a single object.
 */

// import * as fromLayout from '@example-app/core/reducers/layout.reducer';

/**
 * As mentioned, we treat each reducer like a table in a database. This means
 * our top level state interface is just a map of keys to inner state types.
 */

/**
 * Our state is composed of a map of action reducer functions.
 * These reducer functions are called with each dispatched action
 * and the current or initial state and return a new immutable state.
 */
// export const reducers: ActionReducerMap<State, any> = {
// assets: fromAssets.reducers,
// user: fromUser.reducers,
// appWithTrade: fromTrade.reducer
// main: fromMain.reducers
// };

import * as fromSymbol from "@/trade/store/reducers/symbol.reducer";
import { TradeActions } from "@/trade/store/actions";
import * as fromRoot from "@/reducers";

export interface State {
  // assets: fromAssets.State;
  // user: fromUser.State;
  trade: fromSymbol.State;
  user: fromUser.State;
  assets: fromAssets.State;
  // main: fromMain.State;
}

export const reducers: ActionReducerMap<State> = {
  trade: fromSymbol.reducer,
  user: fromUser.reducer,
  assets: fromAssets.reducer
};

// ===================trade start
export const getTradeState = createFeatureSelector<State, fromSymbol.State>(
  "trade"
);

export const symbolLists = createSelector(
  getTradeState,
  (state: any) => {
    return state.selectSymbolResponse.data;
  }
);

export const symbolMap = createSelector(
  getTradeState,
  (state: any) => {
    const ret = {};

    if (!state.selectSymbolResponse.data) {
      return ret;
    }

    for (const item of state.selectSymbolResponse.data) {
      for (const it of item.lists) {
        ret[`${it.symbol}${item.symbol}`] = {
          ...it,
          zi: it.symbol,
          mu: item.symbol
        };
      }
    }

    return ret;
  }
);

export const orderLists = createSelector(
  getTradeState,
  (state: any) => state.selectOrderResponse.data
);

export const activeLists = createSelector(
  getTradeState,
  (state: any) => state.selectActiveResponse.data
);

export const historyLists = createSelector(
  getTradeState,
  (state: any) => state.selectHistoryResponse.data
);

export const activeListsRes = createSelector(
  getTradeState,
  (state: any) => state.selectActiveResponse
);

export const historyListsRes = createSelector(
  getTradeState,
  (state: any) => state.selectHistoryResponse
);

export const addOrderRes = createSelector(
  getTradeState,
  (state: any) => {
    return state.AddOrderResponse;
  }
);

export const delOrderRes = createSelector(
  getTradeState,
  (state: any) => {
    return state.DelOrderResponse;
  }
);
// ===================trade end

// ===================user start

export const getUserState = createFeatureSelector<State, fromUser.State>(
  "user"
);

export const user = createSelector(
  getUserState,
  (state: any) => {
    let ret = false;
    for (const key in state.findUserResponse.data) {
      if (state.findUserResponse.data.hasOwnProperty(key)) {
        const item = state.findUserResponse.data[key];
        if (!!item) {
          ret = true;
        }
      }
    }
    if (ret) {
      return state.findUserResponse.data;
    }
    return null;
  }
);

export const hasAuth = createSelector(
  getUserState,
  (state: any) => state.findUserResponse.code === 200
);

export const userRes = createSelector(
  getUserState,
  (state: any) => state.findUserResponse
);

// ===================user end

// ===================assets start

export const getAssetsState = createFeatureSelector<State, fromAssets.State>(
  "assets"
);

export const assetsLists = createSelector(
  getAssetsState,
  (state: any) => {
    return state.selectAssetsResponse.data;
  }
);

export const assetsMap = createSelector(
  getAssetsState,
  (state: any) => {
    let ret = null;
    if (!!state.selectAssetsResponse.data) {
      ret = {};
      state.selectAssetsResponse.data.forEach(d => {
        ret[d.coin] = {
          ...d
        };
      });
    }
    return ret;
  }
);

export const coinConfigLists = createSelector(
  getAssetsState,
  (state: any) => {
    const ret = [];
    return ret;
  }
);

export const assets = createSelector(
  getAssetsState,
  (state: any) => state.findAssetsResponse.data
);

export const assetsToBtc = createSelector(
  getAssetsState,
  (state: any) => state.findAssetsToBtcResponse.data
);

export const depositHistoryLists = createSelector(
  getAssetsState,
  (state: any) => state.selectDepositHistoryResponse.data
);

export const withdrawHistoryLists = createSelector(
  getAssetsState,
  (state: any) => state.selectWithdrawHistoryResponse.data
);

export const withdrawAddressLists = createSelector(
  getAssetsState,
  (state: any) => state.selectWithdrawAddressResponse.data
);

export const depositAddress = createSelector(
  getAssetsState,
  (state: any) => state.findDepositAddressResponse.data
);

// ======================= assets end

export const pending = (state: State) => {
  return state.assets.pending || state.trade.pending || state.user.pending;
};

// console.log all actions
export function logger(reducer: ActionReducer<State>): ActionReducer<State> {
  return (state: State, action: any): any => {
    const result = reducer(state, action);
    console.groupCollapsed(action.type);
    console.log("prev state", state);
    console.log("action", action);
    console.log("next state", result);
    console.groupEnd();

    return result;
  };
}

/**
 * By default, @ngrx/store uses combineReducers with the reducer map to compose
 * the root meta-reducer. To add more meta-reducers, provide an array of meta-reducers
 * that will be composed to form the root meta-reducer.
 */
export const metaReducers: MetaReducer<State>[] = !environment.production
  ? [logger, storeFreeze]
  : [];
